
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
                            main.c
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
                                                    Forrest Yu, 2005
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/

#include "type.h"
#include "const.h"
#include "protect.h"
//#include "proto.h"
#include "string.h"
#include "proc.h"
#include "proto.h"
#include "global.h"

int writerFirst;
int hungryDE;
void initMutex();
int hungryDetector;
PUBLIC void write(char* name);
PUBLIC void read(char* name);

/*======================================================================*
                            kernel_main
 *======================================================================*/
PUBLIC int kernel_main()
{


	TASK*		p_task		= task_table;
	PROCESS*	p_proc		= proc_table;
	char*		p_task_stack	= task_stack + STACK_SIZE_TOTAL;
	u16		selector_ldt	= SELECTOR_LDT_FIRST;
	int i;
	for (i = 0; i < NR_TASKS; i++) {
		strcpy(p_proc->p_name, p_task->name);	// name of the process
		p_proc->pid = i;			// pid

		p_proc->ldt_sel = selector_ldt;

		memcpy(&p_proc->ldts[0], &gdt[SELECTOR_KERNEL_CS >> 3],
		       sizeof(DESCRIPTOR));
		p_proc->ldts[0].attr1 = DA_C | PRIVILEGE_TASK << 5;
		memcpy(&p_proc->ldts[1], &gdt[SELECTOR_KERNEL_DS >> 3],
		       sizeof(DESCRIPTOR));
		p_proc->ldts[1].attr1 = DA_DRW | PRIVILEGE_TASK << 5;
		p_proc->regs.cs	= ((8 * 0) & SA_RPL_MASK & SA_TI_MASK)
			| SA_TIL | RPL_TASK;
		p_proc->regs.ds	= ((8 * 1) & SA_RPL_MASK & SA_TI_MASK)
			| SA_TIL | RPL_TASK;
		p_proc->regs.es	= ((8 * 1) & SA_RPL_MASK & SA_TI_MASK)
			| SA_TIL | RPL_TASK;
		p_proc->regs.fs	= ((8 * 1) & SA_RPL_MASK & SA_TI_MASK)
			| SA_TIL | RPL_TASK;
		p_proc->regs.ss	= ((8 * 1) & SA_RPL_MASK & SA_TI_MASK)
			| SA_TIL | RPL_TASK;
		p_proc->regs.gs	= (SELECTOR_KERNEL_GS & SA_RPL_MASK)
			| RPL_TASK;

		p_proc->regs.eip = (u32)p_task->initial_eip;
		p_proc->regs.esp = (u32)p_task_stack;
		p_proc->regs.eflags = 0x1202; /* IF=1, IOPL=1 */
		

		// 所有进程初始化，未开始，无睡眠，不饥饿
		p_proc->ifStart = 0;
		p_proc->sleep_ticks = 0; 
		p_proc->hungry = 0;

		p_task_stack -= p_task->stacksize;
		p_proc++;
		p_task++;
		selector_ldt += 1 << 3;
	}
	
	timeUnit= 1000 * HZ / 1000; // 设置单元工作时间单位为1ms（时间片拉长），所有时间片同步


	// 初始化所有進程
	proc_table[0].ticks = proc_table[0].priority = proc_table[0].real_ticks = 2 * timeUnit;
	proc_table[1].ticks = proc_table[1].priority = proc_table[1].real_ticks = 3 * timeUnit;
	proc_table[2].ticks = proc_table[2].priority = proc_table[2].real_ticks = 3 * timeUnit;
	proc_table[3].ticks = proc_table[3].priority = proc_table[3].real_ticks = 3 * timeUnit;
	proc_table[4].ticks = proc_table[4].priority = proc_table[4].real_ticks = 4 * timeUnit;
	proc_table[5].ticks = proc_table[5].priority = proc_table[5].real_ticks = 1 * timeUnit;
	proc_table[6].ticks = proc_table[6].priority = proc_table[6].real_ticks = 1 * timeUnit;
	
	// 此处用于修改读者优先还是写者优先
	writerFirst = 0;

	// 饥饿值初始化
	hungryDE = 0;
	//初始化信號量

	hungryDetector = 1;
	
	initMutex();

	// 此處用於修改最大讀者數量
	MAX_READER = 3;
	
	k_reenter = 0;
	ticks = 0;

	p_proc_ready	= proc_table;

        /* 初始化 8253 PIT */
        out_byte(TIMER_MODE, RATE_GENERATOR);
        out_byte(TIMER0, (u8) (TIMER_FREQ/HZ) );
        out_byte(TIMER0, (u8) ((TIMER_FREQ/HZ) >> 8));

        put_irq_handler(CLOCK_IRQ, clock_handler); /* 设定时钟中断处理程序 */
        enable_irq(CLOCK_IRQ);                     /* 让8259A可以接收时钟中断 */

	restart();

	while(1){}
}


/*======================================================================*
                               initMutex
 *======================================================================*/
void initMutex(){
	r_mutex.s_num = 1;
	r_mutex.lenOfWaitQue = 0;
	w_mutex.s_num = 1;
	w_mutex.lenOfWaitQue = 0;
	s.s_num = 1;
	s.lenOfWaitQue = 0;
	numOfReadP = 0;
}


/*======================================================================*
                               TestA
 *======================================================================*/
void TestA()
{
	int i = 0;
	while (1) {
		read((char*) "A" );
	}
}

/*======================================================================*
                               TestB
 *======================================================================*/
void TestB()
{
	while(1){
		read((char*) "B" );
	}
}

/*======================================================================*
                               TestC
 *======================================================================*/
void TestC()
{
	while(1){
		read((char*) "C" );
	}
}

/*======================================================================*
                               TestD
 *======================================================================*/
void TestD()
{
	while(1){
		write((char*) "D");
	}
}

/*======================================================================*
                               TestE
 *======================================================================*/
void TestE()
{
	while(1){
		write((char*) "E");
	}
}

/*======================================================================*
                               TestF
 *======================================================================*/
void TestF()
{
	while(1){
		if(p_proc_ready->ticks == 1){
			if(numOfReadP==0){
				sys_print_str("F: w | ");
			}
			else{
				sys_print_str("F: r=");
				if (numOfReadP == 1){
					sys_print_str("1");
				}
				else if (numOfReadP == 2){
					sys_print_str("2");
				}
				else if (numOfReadP == 3){
					sys_print_str("3");
				}
				sys_print_str(" | ");
			}

		}
		milli_delay(10);
	}
}

/*======================================================================*
                               TestG
 *======================================================================*/
void TestG()
{
	while(1){
		if (hungryDetector == 1){
			if(p_proc_ready->ticks == 1){
				if (numOfReadP > 1){
					hungryDE++;
				}
				if (numOfReadP == 0){
					hungryDE = 0;
				}
				if (hungryDE > 12){
					p_operation(&w_mutex);
					hungryDE = 0;
					v_operation(&w_mutex);
				}
			}
		}
		milli_delay(10);
	}
}


PUBLIC void write(char* name){
	// 进程执行第一步
	if(p_proc_ready->ticks == p_proc_ready->real_ticks){
		if(!p_proc_ready->ifStart){
			p_proc_ready->ifStart=1;
			sys_print_str_color(name, BLUE_COLOR);
			sys_print_str(" w| ");
			// 如果写者优先
			if (writerFirst == 1){
				p_operation(&s);
			}
			
			p_operation(&w_mutex);

			sys_print_str_color(name, BLUE_COLOR);
			sys_print_str_color(" start write",BLUE_COLOR);
			sys_print_str(" | ");
		}
	}
	// 进程执行结束
	else if(p_proc_ready->ticks == 1){
		p_proc_ready->ifStart=0;

		sys_print_str_color(name, BLUE_COLOR);
		sys_print_str_color(" stop write",BLUE_COLOR);
		sys_print_str(" | ");
		
		v_operation(&w_mutex);
		
		if (writerFirst == 1){
			v_operation(&s);
		}
	}
	
	milli_delay(10);
}

PUBLIC void read(char* name){

	// 进程执行第一步
	if(p_proc_ready->ticks == p_proc_ready->real_ticks){
		if(!p_proc_ready->ifStart){
			p_proc_ready->ifStart=1;
			sys_print_str_color(name,RED_COLOR);
			sys_print_str(" w| ");
			
			if (writerFirst==1){
				p_operation(&s);
			}
			
			p_operation(&r_mutex);
			if(numOfReadP==0){
				p_operation(&w_mutex);
			}
			numOfReadP++;
			if(numOfReadP < MAX_READER){//如果已经达到最大读数量，就不再释放资源
				v_operation(&r_mutex);
			}

			if (writerFirst == 1){
				v_operation(&s);
			}

			sys_print_str_color(name,RED_COLOR);
			sys_print_str_color(" start read",RED_COLOR);
			sys_print_str(" | ");
		}
	}

	// 进程执行第一步
	else if(p_proc_ready->ticks == 1){
		p_proc_ready->ifStart = 0;
		

		sys_print_str_color(name,RED_COLOR);
		sys_print_str_color(" end read",RED_COLOR);
		sys_print_str(" | ");



		
		if(numOfReadP == MAX_READER){
			v_operation(&r_mutex);
		}
		numOfReadP--;
		if(numOfReadP==0){v_operation(&w_mutex);}
		
	}
	milli_delay(10); // 走个过场，读书
}